package com.hd123.rumba.gwt.widget2.client.grid;

import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;
import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant;
import com.hd123.rumba.gwt.widget2.client.fielddef.FieldDef;
import com.hd123.rumba.gwt.widget2.client.fielddef.HasFieldDef;
import com.hd123.rumba.gwt.widget2.client.grid.renderer.RCellRendererFactory;

/**
 * 表格列定义<br>
 * 
 * @author LiQi
 * 
 */
public class RGridColumnDef implements HasFieldDef {

  /** 所属的grid */
  protected RGrid owner;

  /** 列定义序号 */
  protected int index = -1;

  /** 可见列序号 */
  protected int visibleIndex = -1;

  /** 列标题 */
  protected String caption;

  /** 列标题控件 */
  protected Widget headerWidget;

  /** 是否可见 */
  protected boolean visible = true;

  /** 列宽 */
  protected String width;

  /** 横向对齐方式 */
  protected HorizontalAlignmentConstant horizontalAlign = HasAlignment.ALIGN_LEFT;

  /** 竖向对齐方式 */
  protected VerticalAlignmentConstant verticalAlign = HasAlignment.ALIGN_MIDDLE;

  /** 是否允许折行 */
  protected boolean wordWrap = true;

  /** 是否允许点击表头排序 */
  protected boolean sortable = false;

  /** 排序方式，取值范围为SORT_ASC或SORT_DESC，允许null，代表本列没有排序 */
  protected String sort;

  /** 默认排序方式 */
  protected String defaultSort = RGrid.SORT_ASC;

  /** 显示排序方向的图标 */
  protected HTML sortIcon;

  /** 渲染器工厂 */
  protected RCellRendererFactory rendererFactory;

  /** 字段定义 */
  protected FieldDef fieldDef;

  /** 合计方法：无合计 */
  public static final int SUMMARY_METHOD_NONE = 0;

  /** 合计方法：计数 */
  public static final int SUMMARY_METHOD_COUNT = 1;

  /** 合计方法：求和 */
  public static final int SUMMARY_METHOD_SUM = 2;

  /** 合计方法：平均值 */
  public static final int SUMMARY_METHOD_AVERAGE = 3;

  /** 合计方法：最大值 */
  public static final int SUMMARY_METHOD_MAX = 4;

  /** 合计方法：最小值 */
  public static final int SUMMARY_METHOD_MIN = 5;

  /** 合计方法：自定义，由RGrid.summaryProvider进行合计 */
  public static final int SUMMARY_METHOD_CUSTOM = 100;

  /** 合计方法 */
  private int summaryMethod = SUMMARY_METHOD_NONE;

  public RGridColumnDef() {
  }

  /**
   * @param caption
   *          列标题
   */
  public RGridColumnDef(String caption) {
    this();
    setCaption(caption);
  }

  /**
   * @param fieldDef
   *          字段定义
   */
  public RGridColumnDef(FieldDef fieldDef) {
    this();
    setFieldDef(fieldDef);
  }

  /**
   * 所属的grid
   * 
   * @return
   */
  public RGrid getOwner() {
    return owner;
  }

  /**
   * 设置所属的grid
   * 
   * @param owner
   */
  public void setOwner(RGrid owner) {
    this.owner = owner;
  }

  /**
   * 列定义序号，与列是否可见无关
   * 
   * @return
   */
  public int getIndex() {
    return index;
  }

  /**
   * 设置列序号
   * 
   * @param index
   */
  protected void setIndex(int index) {
    this.index = index;
  }

  /**
   * 可见列序号，如果本列不可见则为-1，列定义在被加入到grid之前，visibleIndex也为-1
   * 
   * @return
   */
  public int getVisibleIndex() {
    return visibleIndex;
  }

  /**
   * 设置可见列序号
   * 
   * @param visibleIndex
   */
  protected void setVisibleIndex(int visibleIndex) {
    this.visibleIndex = visibleIndex;
  }

  /**
   * 列标题
   * 
   * @return
   */
  public String getCaption() {
    return caption;
  }

  /**
   * 设置列标题，调用表格的rebuild()后生效
   * 
   * @param caption
   */
  public void setCaption(String caption) {
    this.caption = caption;

    // 应用列标题
    if (visible && owner != null && owner.isBuild()) {
      owner.setText(0, visibleIndex, caption);
    }
  }

  /**
   * 列标题控件
   * 
   * @return
   */
  public Widget getHeaderWidget() {
    return headerWidget;
  }

  /**
   * 设置列标题控件
   * 
   * @param headerWidget
   */
  public void setHeaderWidget(Widget headerWidget) {
    this.headerWidget = headerWidget;
  }

  /**
   * 是否可见
   * 
   * @return
   */
  public boolean isVisible() {
    return visible;
  }

  /**
   * 设置是否可见，调用RGrid.rebuild()后生效
   * 
   * @param visible
   */
  public void setVisible(boolean visible) {
    if (this.visible == visible)
      return;

    this.visible = visible;

    // 重新计算可见列序号
    if (owner != null)
      owner.recalculateColumnVisibleIndex();
  }

  /**
   * 列宽
   * 
   * @return
   */
  public String getWidth() {
    return width;
  }

  /**
   * 设置列宽，立即生效
   * 
   * @param width
   */
  public void setWidth(String width) {
    this.width = width;

    // 应用列宽
    if (visible && owner != null && owner.isBuild()) {
      for (int i = owner.getHeaderRowCount(); i < owner.getRowCount() - owner.getFooterRowCount(); i++) {
        owner.getCellFormatter().setWidth(i, visibleIndex, width);
      }
    }
  }

  /**
   * 横向对齐方式，默认左对齐
   * 
   * @return
   */
  public HorizontalAlignmentConstant getHorizontalAlign() {
    return horizontalAlign;
  }

  /**
   * 设置横向对齐方式
   * 
   * @param horizontalAlign
   */
  public void setHorizontalAlign(HorizontalAlignmentConstant horizontalAlign) {
    this.horizontalAlign = horizontalAlign;

    // 应用对齐方式
    if (visible && owner != null && owner.isBuild()) {
      for (int i = owner.getHeaderRowCount(); i < owner.getRowCount() - owner.getFooterRowCount(); i++) {
        owner.getCellFormatter().setHorizontalAlignment(i, visibleIndex, horizontalAlign);
      }
    }
  }

  /**
   * 单元格竖向对齐方式，默认中间对齐
   * 
   * @return
   */
  public VerticalAlignmentConstant getVerticalAlign() {
    return verticalAlign;
  }

  /**
   * 设置单元格竖向对齐方式
   * 
   * @param verticalAlign
   */
  public void setVerticalAlign(VerticalAlignmentConstant verticalAlign) {
    this.verticalAlign = verticalAlign;

    // 应用对齐方式
    if (visible && owner != null && owner.isBuild()) {
      for (int i = owner.getHeaderRowCount(); i < owner.getRowCount() - owner.getFooterRowCount(); i++) {
        owner.getCellFormatter().setVerticalAlignment(i, visibleIndex, verticalAlign);
      }
    }
  }

  /**
   * 是否允许折行，默认为true
   * 
   * @return
   */
  public boolean isWordWrap() {
    return wordWrap;
  }

  /**
   * 设置是否允许折行，默认为true。
   * <p>
   * 如果设置了setWordWrap(false)即不折行，同时又设置了此列的宽度，则：
   * <li>IE中，内容超长时还是会折行，即宽度优先于不折行。
   * <li>Chrome中，内容超长时会保持不折行把宽度变宽，即不折行优先于宽度。
   * 
   * <p>
   * 所以，建议在需要列不折行时，不要同时设置列的宽度，这样就能确保列不折行。
   * 
   * @param wordWrap
   */
  public void setWordWrap(boolean wordWrap) {
    this.wordWrap = wordWrap;

    // 应用折行
    if (visible && owner != null && owner.isBuild()) {
      for (int i = owner.getHeaderRowCount(); i < owner.getRowCount() - owner.getFooterRowCount(); i++) {
        owner.getCellFormatter().setWordWrap(i, visibleIndex, wordWrap);
      }
    }
  }

  /**
   * 是否允许点击表头排序，默认false
   * 
   * @return
   */
  public boolean isSortable() {
    return sortable;
  }

  /**
   * 设置是否允许点击表头排序，默认false。设置为true后，表头会允许鼠标点击，并显示图标表示排序是顺序还是逆序。真正的
   * 排序动作需要调用
   * {@link RGrid#addRGridSortListener(RGridSortListener)}
   * 在排序事件监听器中完成。例如可在在监听器中调整DataProvider的数据顺序然后刷新表格显示。
   * <p>
   * 另外对于RPagingGrid中包含的RGrid，则不需要设置排序监听器，需要做的是在
   * {@link RGridPageDataProvider#doFetch(int, com.google.gwt.user.client.rpc.AsyncCallback)}
   * 中，在 获得服务器上的数据时，通知服务器排序信息，排序信息可从
   * {@link RGrid#getSortColumnDef()} 获得，至于如何通知服务器排序信息
   * ，则需要开发者自行决定，表格控件和数据提供者都不关心这些。
   * 
   * 
   * @param sortable
   */
  public void setSortable(boolean sortable) {
    this.sortable = sortable;
    if (sortIcon != null)
      sortIcon.setVisible(sortable);
  }

  /**
   * 排序方式，取值范围为{@link RGrid#SORT_ASC}和{@link RGrid#SORT_DESC}
   * ，允许null，代表本列没有排序
   * 
   * @return
   */
  public String getSort() {
    return sort;
  }

  /**
   * 设置排序方式，取值范围为SORT_ASC或SORT_DESC，允许null，代表本列没有排序
   * 
   * @param sort
   */
  protected void setSort(String sort) {
    if (sort != null && !sort.equals(RGrid.SORT_ASC) && !sort.equals(RGrid.SORT_DESC))
      throw new RuntimeException("sort的取值范围应为SORT_ASC或SORT_DESC");
    this.sort = sort;
  }

  /**
   * 默认排序方式，取值范围为SORT_ASC或SORT_DESC
   * 
   * @return
   */
  public String getDefaultSort() {
    return defaultSort;
  }

  /**
   * 设置默认排序方式，取值范围为SORT_ASC或SORT_DESC
   * 
   * @param defaultSort
   */
  public void setDefaultSort(String defaultSort) {
    if (defaultSort != null && !defaultSort.equals(RGrid.SORT_ASC)
        && !defaultSort.equals(RGrid.SORT_DESC))
      throw new RuntimeException("defaultSort的取值范围应为SORT_ASC或SORT_DESC");
    this.defaultSort = defaultSort;
  }

  /**
   * 显示排序方向的图标
   * 
   * @return
   */
  protected HTML getSortIcon() {
    return sortIcon;
  }

  /**
   * 设置显示排序方向的图标
   * 
   * @param sortIcon
   */
  protected void setSortIcon(HTML sortIcon) {
    this.sortIcon = sortIcon;
  }

  /**
   * 渲染器工厂
   * 
   * @return
   */
  public RCellRendererFactory getRendererFactory() {
    return rendererFactory;
  }

  /**
   * 设置渲染器工厂，调用表格的rebuild()后生效<br>
   * 对于纯字符串列，可以不必设置此属性，RGrid会用从provider取得字符串数据直接填充单元格，这样性能较好。
   * 
   * @param rendererFactory
   */
  public void setRendererFactory(RCellRendererFactory rendererFactory) {
    this.rendererFactory = rendererFactory;
  }

  public FieldDef getFieldDef() {
    return fieldDef;
  }

  public void setFieldDef(FieldDef fieldDef) {
    this.fieldDef = fieldDef == null ? null : fieldDef.clone();
    if (this.fieldDef == null)
      return;

    setCaption(fieldDef.getCaption());
  }

  /**
   * 合计方法，取值为SUMMARY_METHOD_*。默认为SUMMARY_METHOD_NONE，即不合计。
   * 取值为SUMMARY_METHOD_CUSTOM时
   * ，会调用RGrid.summaryProvider获得合计值，其它情况下
   * ，都由控件根据合计方法（求和、计数等）自动计算合计值。
   * 
   * @return
   */
  public int getSummaryMethod() {
    return summaryMethod;
  }

  /**
   * 设置合计方法，取值为SUMMARY_METHOD_*。默认为SUMMARY_METHOD_NONE，即不合计。
   * 取值为SUMMARY_METHOD_CUSTOM时
   * ，会调用RGrid.summaryProvider获得合计值，其它情况下
   * ，都由控件根据合计方法（求和、计数等）自动计算合计值。
   * 
   * @param summaryMethod
   */
  public void setSummaryMethod(int summaryMethod) {
    if (this.summaryMethod == summaryMethod)
      return;
    this.summaryMethod = summaryMethod;

    if (owner != null)
      owner.recalculateHasSummary();
  }

  /**
   * 合计方法的描述
   * 
   * @return
   */
  public String getSummaryMethodDesc() {
    return getSummaryMethodDesc(summaryMethod);
  }

  /**
   * 合计方法的描述
   * 
   * @param summaryMethod
   * @return
   */
  public static String getSummaryMethodDesc(int summaryMethod) {
    switch (summaryMethod) {
    case SUMMARY_METHOD_NONE:
      return "";
    case SUMMARY_METHOD_COUNT:
      return "计数";
    case SUMMARY_METHOD_SUM:
      return "求和";
    case SUMMARY_METHOD_AVERAGE:
      return "平均";
    case SUMMARY_METHOD_MAX:
      return "最大值";
    case SUMMARY_METHOD_MIN:
      return "最小值";
    case SUMMARY_METHOD_CUSTOM:
      return "";

    }
    return "";
  }
}
